package com.seaside.park.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.google.gson.JsonObject;
import com.seaside.park.bean.cabinet.Cabinet;
import com.seaside.park.bean.cabinet.CabinetCell;
import com.seaside.park.bean.cabinet.DepositInfo;
import com.seaside.park.bean.cabinet.GoodInfo;
import com.seaside.park.bean.cabinet.vo.CellVO;
import com.seaside.park.bean.cabinet.vo.GoodVO;
import com.seaside.park.bean.cabinet.vo.LocationVO;
import com.seaside.park.mapper.cabinet.CabinetCellMapper;
import com.seaside.park.mapper.cabinet.CabinetMapper;
import com.seaside.park.mapper.cabinet.DepositInfoMapper;
import com.seaside.park.mapper.cabinet.GoodInfoMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.bind.annotation.RequestMapping;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;

@Service
@Slf4j
public class CabinetService {

    @Autowired
    private DepositInfoMapper depositInfoMapper;

    @Autowired
    private CabinetCellMapper cabinetCellMapper;

    @Autowired
    private GoodInfoMapper goodInfoMapper;

    @Autowired
    private CabinetMapper cabinetMapper;


    /**
     * 根据柜子的Id,查询柜子的信息
     */
    public Cabinet getCabinetById(int cabinetId){
        if(cabinetId==0){
            return null;
        }else{
            return cabinetMapper.selectById(cabinetId);
        }
    }

    /**
     * 生成物品存放记录
     */
    private int recordDepostiInfo(String userOpenid, int cabinetId, int type, String duration, int time, String userPhone) {
        DepositInfo depositInfo = new DepositInfo();
        depositInfo.setDepositCabitnet(cabinetId);
        depositInfo.setDepositType(type);
        depositInfo.setDepositDuration(time + duration);
        depositInfo.setUserPhone(userPhone);
        depositInfo.setUserOpenid(userOpenid);

        LocalDateTime now = LocalDateTime.now();

        //计算到期时间
        if (duration.equals("天")) {
            now = now.plusDays(time);
        } else if (duration.equals("周")) {
            now = now.plusWeeks(time);
        } else if (duration.equals("月")) {
            now = now.plusMonths(time);
        }
        depositInfo.setDepositExpireTime(Date.from(now.atZone(ZoneId.systemDefault()).toInstant()));
        depositInfoMapper.insert(depositInfo);

        return depositInfo.getDepositId();
    }

    /**
     * 存放入柜，改变格子的状态
     * 返回存入物品的Id
     */
    @Transactional
    public int depositCell(String userOpenid, int cabinetId, String cellNo, int goodType, String goodName, String duration, int time, String userPhone) {
        int goodId = 0;
        try {
            //开柜失败，则直接返回
            if (!openCabinetCell(cabinetId, cellNo)) {
                return goodId;
            }
            //柜子调用成功，插入存放记录
            int despoitId = recordDepostiInfo(userOpenid, cabinetId, 0, duration, time, userPhone);
            if (despoitId > 0) {
                QueryWrapper<CabinetCell> wrapper = new QueryWrapper<>();
                wrapper.eq("cabinet_id", cabinetId).eq("cell_no", cellNo);
                //查询到格子记录
                CabinetCell cabinetCell = cabinetCellMapper.selectOne(wrapper);
                if (cabinetCell == null || cabinetCell.getUsed() == 1) {
                    log.error("格子状态异常!");
                    return goodId;
                } else {
                    cabinetCell.setCabinetId(cabinetId);
                    cabinetCell.setCellNo(cellNo);
                    cabinetCell.setOpenPhone(userPhone);
                    cabinetCell.setDespoitId(despoitId);
                    //调用物联网平台开柜
                    cabinetCell.setUsed(1);
                    //TODO 生成密码
                    cabinetCell.setOpenPwd(getCharAndNumr(6));
                    //存格子完成，存入物品信息
                    GoodInfo goodInfo = new GoodInfo();
                    goodInfo.setGoodName(goodName);
                    goodInfo.setGoodType(goodType);
                    if (goodInfoMapper.insert(goodInfo) > 0) {
                        goodId = goodInfo.getGoodId();
                        cabinetCell.setGoodId(goodId);
                    } else {
                        log.error("开柜过程中，插入物品数据失败!");
                        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                        return goodId;
                    }
                    UpdateWrapper<CabinetCell> updateWrapper = new UpdateWrapper<>();
                    updateWrapper.eq("cabinet_id", cabinetId).eq("cell_no", cellNo);
                    cabinetCellMapper.update(cabinetCell, updateWrapper);
                }
            } else {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return goodId;
            }
        } catch (Exception e) {
            log.error("存放失败!" + e.getMessage());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return goodId;
        }
        return goodId;
    }

    //Todo 还未处理图片
    public boolean publishGood(int goodId, float goodPrice, String goodDegree, String goodDesc,String goodImages) {
        boolean ret = false;
        try {
            GoodInfo goodInfo = goodInfoMapper.selectById(goodId);
            goodInfo.setGoodPrice(goodPrice);
            goodInfo.setGoodDegree(goodDegree);
            goodInfo.setGoodDesc(goodDesc);
            goodInfo.setGoodImages(goodImages);
            goodInfo.setIfPublish(1);
            goodInfoMapper.updateById(goodInfo);
            ret = true;

        } catch (Exception e) {
            log.error("物品发布超市错误!" + e.getMessage());
        }
        return ret;
    }

    /**
     *
     */
    public boolean openCabinetCellByOpenPwd(int cabinetId, String cellNo,String openPwd){
        //如果使用密码开锁
        if(!(openPwd == null) && !openPwd.equals("")){
            QueryWrapper<CabinetCell> wrapper = new QueryWrapper<>();
            wrapper.eq("cabinet_id",cabinetId).eq("cell_no",cellNo).eq("open_pwd",openPwd);
            List list = cabinetCellMapper.selectList(wrapper);
            if(cabinetCellMapper.selectList(wrapper).size()<1){
                return false;
            }else{
                return openCabinetCell(cabinetId,cellNo);
            }
        }else{
            return false;
        }

    }
    /**
     * 根据柜子ID和格子号码打开格子
     *
     * @param cabinetId 柜子的编号
     * @param cellNo    格子的编号
     * @return 调用物联网打开是否成功
     */
    public boolean openCabinetCell(int cabinetId, String cellNo) {
        boolean ret = false;
        try {
            if(cabinetId==0 || cellNo.equals(null) || cellNo.equals("")){
                return ret;
            }

            //调用物联网平台，打开锁。
            String controllerId = cabinetMapper.selectById(cabinetId).getCabinetController();
            String url = "http://mobile.aowo.vip/smartCabinet/open/" + controllerId + "/" + cellNo;
            RequestConfig requestConfig = RequestConfig.custom()
                    .setConnectTimeout(5000)//一、连接超时：connectionTimeout-->指的是连接一个url的连接等待时间
                    .setSocketTimeout(5000)// 二、读取数据超时：SocketTimeout-->指的是连接上一个url，获取response的返回等待时间
                    .setConnectionRequestTimeout(5000)
                    .build();

            HttpClient client = new DefaultHttpClient();
            HttpGet post = new HttpGet(url);
            post.setConfig(requestConfig);
            HttpResponse response = client.execute(post);

            if (response.getStatusLine().getStatusCode() == 200) {
                HttpEntity resEntity = response.getEntity();
                String message = EntityUtils.toString(resEntity, "utf-8");
                JSONObject result = JSON.parseObject(message);
                int code = result.getIntValue("code");
                if(code==1) {
                    ret = true;
                    log.info("远程开柜调用成功!" + code);
                }
            } else {
                log.info("远程开柜调用失败!");
                return ret;
            }
        } catch (Exception e) {
            log.error("远程开柜发生错误!" + e.getMessage());
        }
        return ret;
    }

    /**
     * 改变格子的状态
     * @param cabinetId 箱子编号
     * @param  cellNo 格子编号
     * @return 是否改变成功
     */
    public boolean changeCellStatus(int cabinetId,String cellNo){
        try{
            QueryWrapper<CabinetCell> wrapper = new QueryWrapper<>();
            wrapper.eq("cabinet_id",cabinetId).eq("cell_no",cellNo);
            CabinetCell cabinetCell = cabinetCellMapper.selectOne(wrapper);
            cabinetCell.setGoodId(0);
            cabinetCell.setDespoitId(0);
            cabinetCell.setUsed(0);
            cabinetCell.setGoodId(0);
            cabinetCell.setOpenPhone("");
            cabinetCell.setOpenPwd("");
            UpdateWrapper<CabinetCell> updateWrapper = new UpdateWrapper<>();
            updateWrapper.eq("cabinet_id",cabinetId).eq("cell_no",cellNo);
            cabinetCellMapper.update(cabinetCell,updateWrapper);
            return true;
        }catch (Exception e){
            log.error("改变格子状态错误!" + e.getMessage());
            return false;
        }
    }

    /**
     * 根据柜子的ID获取该柜子空余的格子
     *
     * @param cabinetId
     * @return
     */
    public List<CabinetCell> getValidCells(int cabinetId) {
        QueryWrapper<CabinetCell> wrapper = new QueryWrapper<>();
        wrapper.eq("cabinet_id", cabinetId).eq("used", 0);
        List<CabinetCell> list = cabinetCellMapper.selectList(wrapper);
        return list;
    }

    /**
     * 根据柜子的ID和用户的微信ID获取用户存入物品的柜子
     *
     * @param cabinetId：柜子编号ID
     * @return 该柜子下所有的箱子列表
     */
    public List<CabinetCell> getUsedCellsByCabinetId(int cabinetId) {
        QueryWrapper<CabinetCell> wrapper = new QueryWrapper<>();
        wrapper.eq("cabinet_id",cabinetId).eq("used",1);
        return cabinetCellMapper.selectList(wrapper);
    }

    /**
     * 根据柜子的ID和用户的微信ID获取用户存入物品的柜子
     *
     * @param cabinetId：柜子编号ID
     * @param userOpenId：      用户的微信ID
     * @return 该柜子下所有的箱子列表
     */
    public List<CellVO> getCellsByUserOpenId(int cabinetId, String userOpenId) {
        return cabinetCellMapper.getCellsByUserOpenId(cabinetId, userOpenId);
    }

    /**
     * 根据柜子的ID和用户的微信ID获取用户存入物品的柜子
     *
     * @param ：柜子编号ID
     * @param ：      用户的微信ID
     * @return 该柜子下所有的箱子列表
     */
    public String getCellsByGoodId(int goodId) {
        LocationVO locationVO = goodInfoMapper.getLocationByGoodId(goodId);
        String ret = "";
        if(locationVO!=null){
            ret = locationVO.getCabinetName()+ locationVO.getCellNo() + "号柜";
        }else{
            ret = "未找到该商品位置!";
        }
        return ret;
    }


    /**
     * 根据柜子的ID获取所有摆放的二手物品
     * @param cabinetId 柜子的编号ID
     * @return List<GoodVO> 货物的List
     */
    public List<GoodVO> getGoodsByCabinetId(int cabinetId){
        return goodInfoMapper.getGoodByCabinetId(cabinetId);
    }

    /**
     * 根据商品信息ID获取该商品的信息
     * @param goodInfoId 柜子的编号ID
     * @return List<GoodVO> 货物的List
     */
    public GoodInfo getGoodInfoById(int goodInfoId){
        return goodInfoMapper.selectById(goodInfoId);
    }

    private static String getCharAndNumr(int length) {
        Random random = new Random();
        StringBuffer valSb = new StringBuffer();
        String charStr = "0123456789abcdefghijklmnopqrstuvwxyz";
        int charLength = charStr.length();

        for (int i = 0; i < length; i++) {
            int index = random.nextInt(charLength);
            valSb.append(charStr.charAt(index));
        }
        return valSb.toString();
    }
}
